#include "StdAfx.h"
#include "PagedBillboardBlock.h"

using namespace std;

namespace FEngine
{
	PagedBillboardBlock::PagedBillboardBlock(float _size, float _maxViewDistance)
		: QuadTreeNode(_size), mMaximumViewDistance(_maxViewDistance)
	{
		mMaximumViewDistance			= _maxViewDistance;

		if (mMaximumViewDistance < 0)
			mMaximumViewDistance = 0;
		mMaximumViewDistanceSquared	= mMaximumViewDistance * mMaximumViewDistance;
	}

	PagedBillboardBlock::~PagedBillboardBlock()
	{
		for (vector<QuadVertex*>::iterator it = mVectorObjectInstance.begin(); it != mVectorObjectInstance.end(); ++it)
		{
			delete (*it)->vertex1;
			delete (*it)->vertex2;
			delete (*it)->vertex3;
			delete (*it)->vertex4;
		}
	}
	
	void PagedBillboardBlock::addBillboard(const Vector3& _pos, const Vector3& _sca, float _windForce, float _windOffset)
	{
		// Create the quad (4 vertices)
		QuadVertex* quad = new QuadVertex();
		quad->vertex1 = new FE_BILLBOARD();
		quad->vertex1->POSITION				= Vector3(-1.0f * _sca.x, -1.0f * _sca.y, 0);
		quad->vertex1->BILLBOARD_POSITION	= Vector3(0, 0, 0);
		quad->vertex1->TEXCOORD				= Vector2(0, 1.0f);
		quad->vertex1->WIND_FORCE			= Vector2(0, 0);
		quad->vertex2 = new FE_BILLBOARD();
		quad->vertex2->POSITION				= Vector3(-1.0f * _sca.x, 1.0f * _sca.y, 0);
		quad->vertex2->BILLBOARD_POSITION	= Vector3(0, 0, 0);
		quad->vertex2->TEXCOORD				= Vector2(0, 0);
		quad->vertex2->WIND_FORCE			= Vector2(_windForce, _windOffset);
		quad->vertex3 = new FE_BILLBOARD();
		quad->vertex3->POSITION				= Vector3(1.0f * _sca.x, 1.0f * _sca.y, 0);
		quad->vertex3->BILLBOARD_POSITION	= Vector3(0, 0, 0);
		quad->vertex3->TEXCOORD				= Vector2(1.0f, 0);
		quad->vertex3->WIND_FORCE			= Vector2(_windForce, _windOffset);
		quad->vertex4 = new FE_BILLBOARD();
		quad->vertex4->POSITION				= Vector3(1.0f * _sca.x, -1.0f * _sca.y, 0);
		quad->vertex4->BILLBOARD_POSITION	= Vector3(0, 0, 0);
		quad->vertex4->TEXCOORD				= Vector2(1.0f, 1.0f);
		quad->vertex4->WIND_FORCE			= Vector2(0, 0);

		// Set the wolrd position of the quad to the bottom
		Vector3 billboardPos = _pos;
		billboardPos.y += (quad->vertex2->POSITION.y - quad->vertex1->POSITION.y) / 2.0f;

		// Set the world position of each vertices
		quad->vertex1->BILLBOARD_POSITION = billboardPos;
		quad->vertex2->BILLBOARD_POSITION = billboardPos;
		quad->vertex3->BILLBOARD_POSITION = billboardPos;
		quad->vertex4->BILLBOARD_POSITION = billboardPos;

		mVectorObjectInstance.push_back(quad);
	}

	int	PagedBillboardBlock::getNumberObject() const
	{
		return mVectorObjectInstance.size();
	}

	int	PagedBillboardBlock::getNumberVisibleObject() const
	{
		return mVectorVisibleObjectInstance.size();
	}
	
	void PagedBillboardBlock::_checkVisibleObjects()
	{
		mVectorVisibleObjectInstance.clear();
		
		if (mVisibility == VISIBILITY_NONE)
			return;

		// Check if the AABB is partially or totally visible
		Vector2 points[] =
		{
			Vector2(mAABB->getMinPoint().x, mAABB->getMinPoint().z),
			Vector2(mAABB->getMaxPoint().x, mAABB->getMaxPoint().z),
			Vector2(mAABB->getMinPoint().x, mAABB->getMaxPoint().z),
			Vector2(mAABB->getMaxPoint().x, mAABB->getMinPoint().z),
		};
		
		Vector2 camPos(CoreEngine::getInstance()->getCamera()->getPosition().x, CoreEngine::getInstance()->getCamera()->getPosition().z);
		

		// We check if the four point of the AABB box are inside the view range
		// Thats not an accurate way of doing a shpere / box intersection, but its fast
		// and we dont need right now to be very precise on this calcul
		int numberPointVisible = 0;
		
		for (int i = 0; i < 4; ++i)
		{
			if ((camPos.x - points[i].x) * (camPos.x - points[i].x) + (camPos.y - points[i].y) * (camPos.y - points[i].y) <= mMaximumViewDistanceSquared)
				numberPointVisible += 1;
		}

		if (numberPointVisible == 0)
			return;

		if (numberPointVisible == 4)
			mVectorVisibleObjectInstance = mVectorObjectInstance;

		else
		{
			// Test each billboard to see if it is in the view range
			Vector2 pt;
			for (vector<QuadVertex*>::iterator it = mVectorObjectInstance.begin(); it != mVectorObjectInstance.end(); ++it)
			{
				pt = Vector2((*it)->vertex1->BILLBOARD_POSITION.x, (*it)->vertex1->BILLBOARD_POSITION.z);
				if ((camPos.x - pt.x) * (camPos.x - pt.x) + (camPos.y - pt.y) * (camPos.y - pt.y) <= mMaximumViewDistanceSquared)
					mVectorVisibleObjectInstance.push_back(*it);
			}
		}
	}
	
	void PagedBillboardBlock::getVectorObjectInstance(std::vector<FE_BILLBOARD*>* _vectorObjectInstance)
	{
		if (mVisibility != VISIBILITY_NONE)
			for (vector<QuadVertex*>::iterator it = mVectorVisibleObjectInstance.begin(); it != mVectorVisibleObjectInstance.end(); ++it)
			{
				_vectorObjectInstance->push_back((*it)->vertex1);
				_vectorObjectInstance->push_back((*it)->vertex2);
				_vectorObjectInstance->push_back((*it)->vertex3);
				_vectorObjectInstance->push_back((*it)->vertex4);
			}
	}

} // namespace FEngine
